package codeanalysis

import (
	"codejy/analysis"
	"codejy/calculate"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
)

func init() {
	globalfunc.RegisterFuncAll("CodeAnalysis", CodeAnalysis)
	globalfunc.RegisterFuncAll("GetTypeInstanceGlobal", GetTypeInstanceGlobal)
	globalfunc.RegisterFuncAll("GetTypeShareInstanceGlobal", GetTypeShareInstanceGlobal)
	globalfunc.RegisterFuncAll("GetTypeInstance", GetTypeInstance)
	globalfunc.RegisterFuncAll("VarTypeToString", VarTypeToString)
	globalfunc.RegisterFuncAll("GetInstanceAddress", GetInstanceAddress)
	globalfunc.RegisterFuncAll("GetFUNCDEF", GetFUNCDEF)
	globalfunc.RegisterFuncAll("GetThis", GetThis)
}

const (

	//数值类型变量
	NUM = iota
	//字符串类型变量
	STR
	//布尔类型变量
	BOOL
	//空
	NULL
	//接收错误
	Receive
	//函数类型定义变量
	FUNCDEF
	//局部类型实例变量
	TypeInstance
	//全局类型实例变量
	TypeInstanceGlobal
	//共享类型实例变量
	TypeShareInstanceGlobal
	//实例地址
	InstanceAddress
	//类型属性
	TypePropert
	//局部变量
	Variable
	//表达式,参数,中的函数调用
	FunctionCall
	//自增自减
	IncrementDecrement
	//全局文件变量赋值
	GlobalProp

	//全局文件方法调用
	GlobalMethod
	//实例地址调用属性
	InstanceAddressProp
	//实例地址调用方法
	InstanceAddressMethod

	//通过this调用属性
	ThisProp
	//通过this调用方法
	ThisMethod

	//当前引用, 返回当前实例地址
	This
	//实例调用属性 实例.属性
	InstanceProp
	//实例调用方法 实例.方法
	InstanceMethod
	//跨文件调用方法
	CrossFileDefineMethod
	//表达式
	EXPRESSION
	//函数命名参数赋值,$name=1
	FuncNameParameterAssignment
	//获取线程id
	ThreadId
	//连续函数调用
	FunctionCallMulti
	//连续引用调用
	UniteCallChain
	//实例创建
	NewInstance
	//全局变量
	VariableGlobal
	//核心函数
	CoreFun
)

// GetTypeInstanceGlobal
func GetTypeInstanceGlobal() int {
	return TypeInstanceGlobal
}
func GetTypeShareInstanceGlobal() int {
	return TypeShareInstanceGlobal
}

// GetTypeInstance
func GetTypeInstance() int {
	return TypeInstance
}

// GetInstanceAddress
func GetInstanceAddress() int {
	return InstanceAddress
} // GetInstanceAddress
func GetFUNCDEF() int {
	return FUNCDEF
}

// GetThis
func GetThis() int {
	return This
}

// 识别变量类型
func CodeAnalysis(threadStore *structdef.ThreadStore, variable string) int {

	//判断是空
	if analysis.IsEmpty(variable) {
		return NULL
	}
	//判断是否是数值类型
	if analysis.IsNumber(variable) {
		return NUM
	}

	//判断是否是布尔类型
	if analysis.IsBool(variable) {
		return BOOL
	}

	//判断是否是获取线程id
	if analysis.IsThreadId(variable) {
		return ThreadId
	}
	//接收错误
	if analysis.IsReceive(variable) {
		return Receive
	}
	//判断是否是实例地址
	if p := analysis.IsInstanceAddress(variable); p {
		return InstanceAddress
	}
	//判断是否是自增自减
	if analysis.IsIncrementDecrement(variable) {
		return IncrementDecrement
	}
	//判断是否是this
	if analysis.IsThis(variable) {
		return This
	}
	//判断是否是表达式
	if calculate.IsExpression(variable) {
		return EXPRESSION
	}
	//判断是否是字符串类型
	if analysis.IsString(variable) {
		return STR
	}
	//连续函数调用()()
	if analysis.IsMethodCallMulti(threadStore, variable) {
		return FunctionCallMulti
	}
	//连续引用调用x().y()
	if analysis.IsUniteCallChain(threadStore, variable) {
		return UniteCallChain
	}

	//判断是否是实例创建
	if analysis.IsNewInstance(variable) {
		return NewInstance
	}

	//判断是否是函数参数赋值语句
	if analysis.IsFuncNameParameter(variable) {
		return FuncNameParameterAssignment
	}

	method := func() int {
		//是否是核心函数
		if p := analysis.IsCoreLibFunCall(variable); p {
			return CoreFun
		}
		//判断是否是this调用方法
		if analysis.IsThisMethodCall(threadStore, variable) {
			return ThisMethod
		}
		//判断是否是全局文件方法调用
		if p := analysis.IsGlobalMethodCall(threadStore, variable); p {
			return GlobalMethod
		}
		//判断是否是实例地址调用方法
		if analysis.IsInstanceAddressMethod(threadStore, variable) {
			return InstanceAddressMethod
		}
		//跨文件调用函数调用
		if p := analysis.IsCrossFileDefineMethodCall(threadStore, variable); p {
			return CrossFileDefineMethod
		}
		//判断是否是实例函数调用
		if analysis.IsInstanceMethodCall(threadStore, variable) {
			return InstanceMethod
		}
		//判断是否是函数调用
		if analysis.IsMethodCall(threadStore, variable) {
			return FunctionCall
		}
		return -1
	}()
	if method != -1 {
		return method
	}

	//方法私有变量>类型属性>全局
	varName := func() int {

		//判断是否是实例地址调用属性  @#@xx@#@.xxx
		if analysis.IsInstanceAddressProp(threadStore, variable) {
			return InstanceAddressProp
		}
		//判断是否是global.xx调用
		if p := analysis.IsGlobalProp(threadStore, variable); p {
			return GlobalProp
		}
		//判断是否是this.xxx调用属性
		if analysis.IsThisProp(threadStore, variable) {
			return ThisProp
		}
		//判断是否是实例属性调用 xxx.xxx
		if analysis.IsInstanceProp(threadStore, variable) {
			return InstanceProp
		}
		//判断是否是类型实例变量
		p := analysis.IsInstance(threadStore, variable)
		if p {
			return TypeInstance
		}
		//判断是否是变量
		if _, p = store.GetVariable(threadStore, variable); p {
			return Variable
		}
		//判断是否是实例内的属性变量
		if p = analysis.IsInstanceAttribute(threadStore, variable); p {
			return TypePropert
		}
		//判断是否是全局实例变量
		if p = analysis.IsGlobalInstance(threadStore, variable); p {
			return TypeInstanceGlobal
		}
		//判断是否是全局变量
		if _, p = store.GetGlobalVariable(threadStore, variable); p {
			return VariableGlobal
		}

		return -1
	}()
	if varName != -1 {
		return varName

	}

	//判断是否是函数定义
	if store.SearchFunDefinition(threadStore, variable) != nil {
		return FUNCDEF
	}

	return -1
}

// 根据变量类型,中文转换
func VarTypeToString(varType int) string {
	switch varType {
	case NUM:
		return "数字"
	case STR:
		return "字符串"
	case BOOL:
		return "布尔"
	case NULL:
		return "空"
	case FUNCDEF:
		return "函数定义变量"
	case TypeInstance:
		return "实例变量"
	case TypeInstanceGlobal:
		return "全局实例变量"
	case TypeShareInstanceGlobal:
		return "全局共享实例变量"
	case InstanceAddress:
		return "实例地址变量"
	case Variable:
		return "变量"
	case VariableGlobal:
		return "全局变量"
	default:
		return "未知"
	}
}

// 判断是实例变量
func IsInstanceVariable(threadStore *structdef.ThreadStore, variable string) int {
	//判断是否是类型实例变量
	p := analysis.IsInstance(threadStore, variable)
	if p {
		return TypeInstance
	}
	//判断是否是全局实例变量
	if p = analysis.IsGlobalInstance(threadStore, variable); p {
		return TypeInstanceGlobal
	}
	return -1
}

// 判断是基础类型,字符串,整数,布尔 ,不包括小数
func IsBaseNotFloatType(variable string) int {
	if analysis.IsString(variable) {
		return STR
	}
	if analysis.IsBool(variable) {
		return BOOL
	}
	if analysis.IsInt(variable) {
		return NUM
	}
	return -1
}
